package k3_IO.p2_fileStream.demo01;


import java.io.*;
import java.nio.charset.Charset;

public class FileStream {

    /**
     * 使用文件字节输出流
     */
    public static void fileOutputStream() throws Exception {

        FileOutputStream fos = new FileOutputStream("E://test1",true);

        //每次直接写入一个字节
//        fos.write(97);
//        fos.write(98);
//        fos.write(99);

        //一次写入多个字节
        byte[] b = {100,101,102,103,104};
//        fos.write(b);

        //把字符串转成字节数组后，写入到文件中
//        String s = "hello";
//        byte[] sb = s.getBytes();
//        fos.write(sb);

        //字节输出流中空格换行等的写入
//        fos.write(97);
//        fos.write("\n".getBytes());
//        fos.write(98);
//        fos.write(" ".getBytes());
//        fos.write(99);

        //将字节数组中的指定位置的字节写入到文件中
        fos.write(b,2,2);

        fos.flush();

        fos.close();
    }

    /**
     * 使用字节输入流
     */
    public static void fileInputStream() throws IOException {

        FileInputStream fis = new FileInputStream("E://test1.txt");

        int tempRead = 0;

        //read无参 表示一次执行只读取一个字节，类似与迭代器，如果读到文件末尾，返回为-1
//        while((tempRead=fis.read())!=-1){
//            System.out.print((char) tempRead);
//        }

        //创建一个临时的缓冲区
        byte[] byteBuffer = new byte[3];
        //初始化每次读取的实际字节的数量
        int length = 0;
        while((length = fis.read(byteBuffer))!=-1){
            //根据实际的数量转成字符串输出
            System.out.println(new String(byteBuffer,0,length));
        }


//        while((length = fis.read(byteBuffer))!=-1){
//            //根据缓冲区中指定范围的字节转成字符串
//            System.out.println(new String(byteBuffer,0,1));
//        }

        //jdk9版本开始提供的方法，一次性可以读取所有的内容
//        byte[] allBytes = fis.readAllBytes();
//        System.out.println(new String(allBytes));


        fis.close();
    }

    /**
     * 使用字符输出流
     */
    public static void fileWriter() throws Exception {
        //我们要定义的是字符输出流，原码中创建了一个字节输出流的对象，通过转换流对这个字节输出流加上了字符编码
        //字符=字节+编码表
        FileWriter fw = new FileWriter("E://test3", Charset.forName("gb2312"));
        fw.write(97);
        fw.write("\thello");
        fw.write("world",1,3);
        fw.write(new char[]{'\t','a','b','c'});
        fw.write(new char[]{'\t','q','\n','w','e'},2,3);
        fw.append('中');
        fw.append("\ttoday");
        fw.append("question",3,5);

        fw.flush();
        fw.close();
    }

    /**
     * 使用字符输入流
     * 读取的时候要使用写入时使用的字符编码表
     */
    public static void fileReader() throws Exception {


        FileReader fr = new FileReader("E://test3", Charset.forName("gb2312"));

        //一个字符一个字符的读取
//        int tempByte = 0;
//        while((tempByte = fr.read())!=-1){
//            System.out.print((char) tempByte);
//        }

        //创建字符缓冲区
        char[] charBuffer = new char[3];
        //初始化一个实际读取的长度
        int length = 0;
        while((length = fr.read(charBuffer))!=-1){
            System.out.println(new String(charBuffer,0,length));
        }

        fr.close();
    }

    /**
     * 转换流
     *  InputStreamReader
     *      读的原始数据是字节，按照指定的编码表转成字符返回给使用者
     *  OutputStreamWriter
     *      把使用者要写出的字符，按照指定的编码表转成字节写入到磁盘中
     *  从JDK11开始,不需要特意使用转换流来指定编码表，字符流已经可以指定了
     */
    public static void fileTransferStream() throws Exception {

        try(
            //try() 小括号中创建的流对象，可以由JVM帮我们自动关闭资源，而无需手动关闭
            //在小括号中定义的流对象，相当于是final修饰的，不允许再做修改
            FileOutputStream fos = new FileOutputStream("E://test6.txt");
            OutputStreamWriter osw = new OutputStreamWriter(fos,Charset.forName("gb2312"));
        ) {
            osw.write("hello world");
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws Exception {

//        FileStream.fileOutputStream();
//        FileStream.fileInputStream();
//        FileStream.fileWriter();
//        FileStream.fileReader();
        FileStream.fileTransferStream();

    }
}
